package com.zmn.oms.zmn.business.impl.proxy;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.ltsopensource.core.domain.Job;
import com.google.common.collect.Lists;
import com.zmn.base.channel.common.dro.ChannelDRO;
import com.zmn.base.channel.dubbo.interfaces.channel.ChannelListRemoteService;
import com.zmn.base.common.data.common.dro.area.AreaDRO;
import com.zmn.base.common.data.dubbo.interfaces.area.AreaListRemoteService;
import com.zmn.base.product.common.dto.product.ProductBaseQuery;
import com.zmn.base.product.common.dto.product.ec.ProductBaseDRO;
import com.zmn.base.product.dubbo.interfaces.product.foreign.ProductForeignListRemoteService;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.constant.StatusConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.amount.AmountUtil;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.math.MathUtil;
import com.zmn.common.utils.math.MoneyUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.consts.GateTypeConsts;
import com.zmn.log.client.user.operation.AddUserOperationLogRequest;
import com.zmn.log.client.user.operation.UserOperationLogClient;
import com.zmn.log.client.user.operation.item.DeviceLogItem;
import com.zmn.log.client.user.operation.item.EntryLogItem;
import com.zmn.log.client.user.operation.item.event.AddOrderEventLogItem;
import com.zmn.manager.lts.interfaces.task.TaskManager;
import com.zmn.manager.redis.lock.DistributedLock;
import com.zmn.manager.redis.lock.DistributedLockUtils;
import com.zmn.mos.common.dio.order.add.ChannelApiOrderAddDIO;
import com.zmn.mos.common.dio.order.add.nest.ChannelApiExtraData;
import com.zmn.mos.common.dio.order.add.nest.OrderBaseInfo;
import com.zmn.mos.common.dio.order.add.nest.OrderProductDIO;
import com.zmn.mos.common.dio.order.add.nest.UserDIO;
import com.zmn.mos.common.dio.order.add.shop.ExternalShopDIO;
import com.zmn.mos.common.dro.order.OrderAddDRO;
import com.zmn.mos.dubbo.interfaces.order.ChannelApiOrderRemoteService;
import com.zmn.oms.business.interfaces.comment.OrderCommentBService;
import com.zmn.oms.business.interfaces.discount.OrderDiscountBService;
import com.zmn.oms.business.interfaces.log.OrderLogBService;
import com.zmn.oms.business.interfaces.order.DuplicateOrderBService;
import com.zmn.oms.business.interfaces.servtype.ServItemBService;
import com.zmn.oms.business.interfaces.work.OrderWorkAmountBService;
import com.zmn.oms.business.interfaces.work.OrderWorkListBService;
import com.zmn.oms.common.constant.LockConsts;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderLogConsts;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.common.dto.MapDTO;
import com.zmn.oms.common.dto.OmsBaseOperator;
import com.zmn.oms.common.dto.OmsOperator;
import com.zmn.oms.common.enums.EncryptFieldTypeEnum;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.common.exception.chan.ChannelFacadeException;
import com.zmn.oms.common.utils.FilterUtil;
import com.zmn.oms.manager.utils.TaskConsts;
import com.zmn.oms.model.bo.order.OrderBO;
import com.zmn.oms.model.dto.comment.OrderCommentDTO;
import com.zmn.oms.model.dto.discount.AddDiscountDTO;
import com.zmn.oms.model.dto.order.open.AvailableTimeslotsQuery;
import com.zmn.oms.model.dto.order.proxy.*;
import com.zmn.oms.model.dto.serviceitem.GetServiceItemDTO;
import com.zmn.oms.model.dto.work.modify.CheckQuotationTypeOrderDTO;
import com.zmn.oms.model.dto.work.modify.ServiceItemQueryDTO;
import com.zmn.oms.model.dto.work.modify.ServiceItemResultDTO;
import com.zmn.oms.model.dto.work.modify.amount.ZsUpdateChannelPrepayAmountDTO;
import com.zmn.oms.model.dto.work.modify.must.ZsCancelDTO;
import com.zmn.oms.model.dto.work.modify.must.ZsOrderPayDTO;
import com.zmn.oms.model.dto.work.workamount.ValidateWorkAmountDTO;
import com.zmn.oms.model.entity.chan.OrderClueDetail;
import com.zmn.oms.model.entity.detail.OrderDetail;
import com.zmn.oms.model.entity.log.OrderLog;
import com.zmn.oms.model.entity.order.Order;
import com.zmn.oms.model.entity.order.OrderExtend;
import com.zmn.oms.model.entity.order.OrderListQuery;
import com.zmn.oms.model.entity.order.OrderQuery;
import com.zmn.oms.model.entity.outermap.OrderOuterMap;
import com.zmn.oms.model.entity.outermap.OrderOuterMapQuery;
import com.zmn.oms.model.entity.product.OrderProduct;
import com.zmn.oms.model.entity.serviceitem.OrderServiceItem;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.entity.work.OrderWorkQuery;
import com.zmn.base.oms.common.model.es.orderwork.EsOrderWork;
import com.zmn.oms.model.vo.order.open.AvailableTimeslotsVO;
import com.zmn.oms.model.vo.order.proxy.OrderInfoVO;
import com.zmn.oms.model.vo.product.OrderProductVO;
import com.zmn.oms.model.vo.work.schedule.OrderScheduleVO;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.order.OrderExtendService;
import com.zmn.oms.services.interfaces.order.OrderService;
import com.zmn.oms.services.interfaces.orderencrypt.OrderEncryptService;
import com.zmn.oms.services.interfaces.outermap.OrderOuterMapService;
import com.zmn.oms.services.interfaces.product.OrderProductService;
import com.zmn.oms.services.interfaces.work.OrderWorkAmountService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.third.base.util.ProductIdUtil;
import com.zmn.oms.third.base.util.ThirdOrderUtil;
import com.zmn.oms.third.taobao.TaobaoMapper;
import com.zmn.oms.zmn.aop.OrderWorkLogUtils;
import com.zmn.oms.zmn.business.interfaces.chan.FacadeOrderClueDetailBService;
import com.zmn.oms.zmn.business.interfaces.discount.ChannelDiscountService;
import com.zmn.oms.zmn.business.interfaces.proxy.ProxyOrderBService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkScheduleBService;
import com.zmn.oms.zmn.business.interfaces.work.autoflow.WorkFlowContextBService;
import com.zmn.oms.zmn.business.interfaces.work.orderpay.ZsOrderPayBService;
import com.zmn.oms.zmn.normal.business.interfaces.order.FactoryOrderBService;
import com.zmn.oms.zmn.normal.business.interfaces.order.ZsNormalOrderBService;
import com.zmn.oms.zmn.normal.business.interfaces.work.ZsNormalWorkBService;
import com.zmn.oms.zmn.normal.business.interfaces.work.masterwork.ZsNormalMasterWorkBService;
import com.zmn.pay.common.constant.PayConsts;
import com.zmn.uuc.common.dio.user.UserRegisterByMobileNoCaptchaDIO;
import com.zmn.uuc.common.dio.user.UserTempRegisterDIO;
import com.zmn.uuc.common.dro.user.UserBaseDRO;
import com.zmn.uuc.common.query.user.UserMobilePlatQuery;
import com.zmn.uuc.dubbo.interfaces.user.UserListRemoteService;
import com.zmn.uuc.dubbo.interfaces.user.UserModifyRemoteService;
import com.zmn.uuc.dubbo.interfaces.user.UserRegisterRemoteService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 类描述：订单接口代理
 *
 * @author liuying
 * @date 2019/02/18 17:04
 */
@Service
public class ProxyOrderBServiceImpl implements ProxyOrderBService {

    private Logger logger = LoggerFactory.getLogger(ProxyOrderBServiceImpl.class);

    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private ProductForeignListRemoteService productForeignListRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private AreaListRemoteService areaListRemoteService;
    // @Reference(version = com.zmn.ums.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false)
    // private ComplainModifyRemoteService complainModifyRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private ChannelListRemoteService channelListRemoteService;
    @Reference(version = com.zmn.uuc.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private UserRegisterRemoteService userRegisterRemoteService;
    @Reference(version = com.zmn.uuc.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private UserListRemoteService userListRemoteService;
    @Reference(version = com.zmn.uuc.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private UserModifyRemoteService userModifyRemoteService;
//    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
//    private FactoryListRemoteService factoryListRemoteService;
    @Reference(version = com.zmn.mos.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false)
    private ChannelApiOrderRemoteService channelApiOrderRemoteService;

    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderWorkService orderWorkService;
    @Autowired
    private ZsNormalOrderBService zsNormalOrderBService;
    @Autowired
    private OrderWorkListBService orderWorkListBService;
    @Autowired
    private OrderExtendService orderExtendService;
    @Autowired
    private ZsOrderPayBService zsOrderPayBService;
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private OrderProductService orderProductService;
    @Autowired
    private OrderLogBService orderLogBService;
    @Autowired
    private ZsNormalWorkBService zsNormalWorkBService;
    @Autowired
    private OrderCommentBService orderCommentBService;
    @Autowired
    private OrderOuterMapService orderOuterMapService;
    @Autowired
    private ZsNormalMasterWorkBService zsNormalMasterWorkBService;
    @Autowired
    private OrderWorkAmountBService orderWorkAmountBService;
    @Autowired
    private OrderWorkAmountService orderWorkAmountService;
    @Autowired
    private OrderDiscountBService orderDiscountBService;
    @Autowired
    private DuplicateOrderBService duplicateOrderBService;
    @Autowired
    private ChannelDiscountService channelDiscountService;
    @Autowired
    private ZsOrderWorkScheduleBService zsOrderWorkScheduleBService;
    @Autowired
    private FactoryOrderBService factoryOrderBService;
    @Autowired
    private FacadeOrderClueDetailBService facadeOrderClueDetailBService;
    @Autowired
    private OrderEncryptService orderEncryptService;
    @Autowired
    private TaskManager taskManager;
    @Autowired
    private WorkFlowContextBService workFlowContextBService;
    @Resource
    private UserOperationLogClient logClient;
    @Autowired
    private ServItemBService servItemBService;

    @Override
    public int orderListCount(OrderListQuery orderListQuery) {
        OrderWorkQuery query = new OrderWorkQuery();
        query.setUserId(orderListQuery.getUserId());

        if (StringUtils.isNotBlank(orderListQuery.getOuterUserId())) {
            query.setOuterUserId(orderListQuery.getOuterUserId());
        }

        if (orderListQuery.getChannelId() != null) {
            query.setChannelIdList(Lists.newArrayList(orderListQuery.getChannelId()));
        }

        if (StringUtils.isNotBlank(orderListQuery.getCheckoutTime())) {
            query.setCheckoutTime(orderListQuery.getCheckoutTime());
        }

        if (StringUtils.isNotBlank(orderListQuery.getReceiveTime())) {
            query.setReceiveTime(orderListQuery.getReceiveTime());
        }

        if (StringUtils.isNotBlank(orderListQuery.getConcatPhone())) {
            query.setConcatPhone(orderListQuery.getConcatPhone());
        }

        return orderWorkListBService.countOrderWorkByQuery(query);
    }

    @Override
    public List<OrderInfoVO> orderList(OrderListQuery orderListQuery) {
        List<OrderInfoVO> orderInfoVOList = Lists.newArrayList();
        OrderWorkQuery query = new OrderWorkQuery();
        query.setUserId(orderListQuery.getUserId());

        if (StringUtils.isNotBlank(orderListQuery.getOuterUserId())) {
            query.setOuterUserId(orderListQuery.getOuterUserId());
        }

        if (orderListQuery.getChannelId() != null) {
            query.setChannelIdList(Lists.newArrayList(orderListQuery.getChannelId()));
        }

        if (StringUtils.isNotBlank(orderListQuery.getCheckoutTime())) {
            query.setCheckoutTime(orderListQuery.getCheckoutTime());
        }

        if (StringUtils.isNotBlank(orderListQuery.getReceiveTime())) {
            query.setReceiveTime(orderListQuery.getReceiveTime());
        }

        if (StringUtils.isNotBlank(orderListQuery.getConcatPhone())) {
            query.setConcatPhone(orderListQuery.getConcatPhone());
        }

        if (query.getUserId() != null || StringUtils.isNotBlank(query.getOuterUserId())) {
            query.setPageSize(100);
        } else {
            query.setPageSize(300);
        }

        query.setPageIndex(1);

        List<EsOrderWork> esOrderWorkList = orderWorkListBService.listPageOrderWorkByQuery(query);
        // 解密电话和地址
        orderEncryptService.batchDecryptEsOrderWork(esOrderWorkList, EncryptFieldTypeEnum.USER_TELPHONE, EncryptFieldTypeEnum.USER_ADDRESS);

        for (EsOrderWork esOrderWork : esOrderWorkList) {
            OrderInfoVO orderInfoVO = BeanMapper.map(esOrderWork, OrderInfoVO.class);
            int orderStatus = OrderStatusConsts.getOrderStatus(esOrderWork.getStatus(), esOrderWork.getResultStatus());
            orderInfoVO.setStatusName(OrderStatusConsts.getOrderStatusName(orderStatus));
            orderInfoVOList.add(orderInfoVO);

            if (StringUtil.isNotBlank(orderInfoVO.getMasterName())) {
                orderInfoVO.setMasterName(String.format("%s工程师", orderInfoVO.getMasterName().substring(0,1)));
            }
        }
        return orderInfoVOList;
    }

    @Override
    public OrderInfoVO queryOrderById(OrderQuery orderQuery) throws OmsBaseException {
        Long orderId = this.getOrderId(orderQuery);

        // 获取订单新
        OrderWork dbOrderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);

        if (dbOrderWork == null) {
            throw new OmsBaseException("订单不存在！");
        }
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(orderId);

        OrderInfoVO orderInfoVO = BeanMapper.map(dbOrderWork, OrderInfoVO.class);

        orderInfoVO.setMasterBindTelephone(orderDetail.getBindTelephone());
        if (StringUtils.isNotBlank(orderInfoVO.getMasterName())) {
            orderInfoVO.setMasterName(String.format("%s工程师", orderInfoVO.getMasterName().substring(0,1)));
        }


        orderInfoVO.setTelephone(orderDetail.getTelephone());
        orderInfoVO.setStreet(StringUtils.defaultString(orderDetail.getStreet()));
        orderInfoVO.setAddress(String.format("%s%s%s%s%s", orderDetail.getProvinceName(), orderDetail.getCityName(), orderDetail.getCountyName(), StringUtils.defaultString(orderDetail.getStreet()), StringUtils.defaultString(orderDetail.getAddress())));
        orderInfoVO.setStatusName(OrderStatusConsts.getWorkStatusName(dbOrderWork.getStatus()));
        orderInfoVO.setResultStatusName(OrderStatusConsts.getWorkResultStatusName(dbOrderWork.getResultStatus()));
        orderInfoVO.setProductInfo(orderDetail.getProductInfo());
        orderInfoVO.setServCategName(orderDetail.getServCategName());
        orderInfoVO.setContactName(StringUtils.defaultIfBlank(orderDetail.getContactName(), orderDetail.getUserName()));
        orderInfoVO.setCityId(dbOrderWork.getNaturalCityId());
        orderInfoVO.setLongitude(orderDetail.getLongitude());
        orderInfoVO.setLatitude(orderDetail.getLatitude());

        // 处理resultTime 为空的情况，历史数据问题
        if (Objects.equals(dbOrderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DISCARD) && dbOrderWork.getResultTime() == null) {
            orderInfoVO.setResultTime(dbOrderWork.getUpdateTime());
        } else if (Objects.equals(dbOrderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_FAIL) && dbOrderWork.getResultTime() == null) {
            orderInfoVO.setResultTime(Optional.ofNullable(dbOrderWork.getCheckoutTime()).orElse(dbOrderWork.getUpdateTime()));
        }

        // 查询产品信息
        List<OrderProduct> orderProductList = orderProductService.listOrderProductByOrderId(orderId);
        List<OrderProductVO> productList = Lists.newArrayListWithExpectedSize(orderProductList.size());

        for (OrderProduct orderProduct : orderProductList) {
            OrderProductVO orderProductVO = new OrderProductVO();
            orderProductVO.setProductId(orderProduct.getProductId());
            orderProductVO.setProductName(orderProduct.getProductName());
            orderProductVO.setNumber(orderProduct.getNumber());
            orderProductVO.setPrice(orderProduct.getPrice());
            orderProductVO.setUnit(orderProduct.getProductUnit());
            String fault = null;
            if (StringUtils.isNotBlank(orderProduct.getFault())) {
                try {
                    List<MapDTO> faultList = JSON.parseArray(orderProduct.getFault(), MapDTO.class);
                    fault = StringUtils.join(Optional.ofNullable(faultList).orElse(Lists.newArrayListWithCapacity(0)).stream().map(MapDTO::getMapName).collect(Collectors.toList()), "，");
                } catch (Exception ex) {
                }
            }
            orderProductVO.setRemark(String.format("%s %s", StringUtils.defaultString(fault), StringUtils.defaultString(orderProduct.getRemark())));
            productList.add(orderProductVO);
        }

        orderInfoVO.setProductList(productList);

        // 扩展信息
        OrderExtend orderExtend = orderExtendService.findOrderExtendByOrderId(orderId);
        if (orderExtend != null) {
            orderInfoVO.setOuterData(orderExtend.getOuterData());
            orderInfoVO.setExtOuterData(orderExtend.getExtOuterData());
            orderInfoVO.setExtraData(orderExtend.getExtraData());
        }

        return orderInfoVO;
    }

    /**
     * Proxy录单
     * @param createOrderDTO
     * @return
     * @throws OmsBaseException
     */
    @Override
    public OrderBO createOrder(CreateOrderDTO createOrderDTO) throws OmsBaseException {
        logger.info("[ProxyService-createOrder] CreateOrderDTO:[{}]", JSON.toJSONString(createOrderDTO));
        // 是否是由渠道门户接口接入的订单
        boolean isFromFacadeInterfaceOrder = Objects.nonNull(createOrderDTO.getOrderClueId());
        OrderBO orderBO = null;
        try {
            orderBO = doCreateOrder(createOrderDTO);
        } catch (Exception e) {
            logger.info("常规保存订单失败。 ChannelId:[{}], OuterData:[{}]",
                    createOrderDTO.getChannelId(), createOrderDTO.getOuterData());
            logger.error(e.getMessage(), e);

            // 渠道门户接口接入的订单，将线索存入线索池
            if (isFromFacadeInterfaceOrder) {
                try {
                    this.saveAsOrderClueDetail(createOrderDTO, e.getMessage());
                } catch (ChannelFacadeException cfe) {
                    logger.error(String.format("保存订单到线索池失败：%s, CreateOrderDTO=[%s]",
                            cfe.getMessage(), JSON.toJSONString(createOrderDTO)), cfe);
                    throw e;
                }
            }
            // 非渠道门户接口接入的订单，忽略城市和产品信息，第二次保存订单，保存后需人工处理
            else {
                createOrderDTO.getOrderProductList().get(0).setProductShowType(GlobalConsts.NO);
                createOrderDTO.getOrderProductList().get(0).setProductId(OrderConsts.CHANNEL_DISABLED_PRODUCT_ID);
                ThirdOrderUtil.fillDefaultOrderInfo(createOrderDTO, "；常规保存订单失败，需人工确认");
                orderBO = doCreateOrder(createOrderDTO);
            }
        }
        return orderBO;
    }

    private OrderBO doCreateOrder(CreateOrderDTO createOrderDTO) throws OmsBaseException {
        // 补全城市ID
        if (createOrderDTO.getCityId() == null) {
            Integer cityId = null;
            // 1.存在经纬度时，优先使用经纬度获取
            if (createOrderDTO.getLongitude() != null && createOrderDTO.getLatitude() != null) {
                cityId = Optional.ofNullable(areaListRemoteService.getAreaByLatAndLng(createOrderDTO.getLongitude(), createOrderDTO.getLatitude()))
                        .map(areaResponse -> areaResponse.isSuccess() ? areaResponse.getData() : null)
                        .map(areaDRO -> areaDRO.getParentId())
                        .get();
            }
            // 2.不能通过经纬度获取cityId时，使用逆地址解析获取
            if (cityId == null) {
                String addressInfo = String.format("%s%s",
                        StringUtil.isBlank(createOrderDTO.getStreet()) ? "" : createOrderDTO.getStreet().trim(),
                        StringUtil.isBlank(createOrderDTO.getAddress()) ? "" : createOrderDTO.getAddress().trim()
                );
                if (StringUtil.isNotBlank(addressInfo)) {
                    cityId = Optional.ofNullable(areaListRemoteService.getAreaByAddress(addressInfo))
                            .map(areaResponse -> areaResponse.isSuccess() ? areaResponse.getData() : null)
                            .map(areaDRO -> areaDRO.getParentId())
                            .get();
                }
            }
            // 3.无法获取的情况，默认为重庆
            createOrderDTO.setCityId(cityId == null ? 500100 : cityId);
        }

//        ChannelApiOrderAddDIO addDIO = Objects.equals(GlobalConsts.YES, createOrderDTO.getFactory())
//                ? this.buildFactoryChannelApiOrderAddDIO(createOrderDTO)
//                : this.buildNormalChannelApiOrderAddDIO(createOrderDTO);
        if (Objects.equals(GlobalConsts.YES, createOrderDTO.getFactory())) {
            throw new OmsBaseException("厂商功能已下线");
        }
        ChannelApiOrderAddDIO addDIO = this.buildNormalChannelApiOrderAddDIO(createOrderDTO);
        logger.info("渠道接口下单入参[{}]", JSON.toJSONString(addDIO));
        ResponseDTO<OrderAddDRO> responseDTO = channelApiOrderRemoteService.addOrder(addDIO);
        logger.info("渠道接口下单出参[{}]", JSON.toJSONString(responseDTO));

        if (!responseDTO.isSuccess()) {
            throw new OmsBaseException(responseDTO.getMessage());
        }

        OrderBO orderBO = new OrderBO();
        {
            Long orderId = responseDTO.getData().getOrderId();
            Order dbOrder = orderService.findOrderByKeySrcMaster(orderId);
            orderBO.setOrder(dbOrder);
            OrderWork dbOrderWork = orderWorkService.findOrderWorkByKeySrcMaster(orderId, orderId);
            orderBO.setOrderWork(dbOrderWork);
            OrderDetail dbOrderDetail = orderDetailService.findOrderDetailByKeySrcMaster(orderId);
            orderBO.setOrderDetail(dbOrderDetail);
            List<OrderProduct> dbProductList = orderProductService.listOrderProductByOrderIdSrcMaster(orderId);
            orderBO.setOrderProductList(dbProductList);
        }

        // 录单埋点
        //this.addOrderEventLog(orderBO, createOrderDTO);

        return orderBO;
    }

    /**
     * OpenAPI录单
     * @param createOrderDTO
     * @return
     * @throws Exception
     */
    @Override
    public OrderBO createOrder(com.zmn.oms.model.dto.order.open.CreateOrderDTO createOrderDTO) throws OmsBaseException {
        // 补全城市ID
        if (createOrderDTO.getCityId() == null) {
            Integer cityId = null;
            // 1.存在经纬度时，优先使用经纬度获取
            if (createOrderDTO.getLongitude() != null && createOrderDTO.getLatitude() != null) {
                cityId = Optional.ofNullable(areaListRemoteService.getAreaByLatAndLng(createOrderDTO.getLongitude(), createOrderDTO.getLatitude()))
                        .map(areaResponse -> areaResponse.isSuccess() ? areaResponse.getData() : null)
                        .map(areaDRO -> areaDRO.getParentId())
                        .get();
            }
            // 2.不能通过经纬度获取cityId时，使用逆地址解析获取
            if (cityId == null) {
                String addressInfo = String.format("%s%s",
                        StringUtil.isBlank(createOrderDTO.getStreet()) ? "" : createOrderDTO.getStreet().trim(),
                        StringUtil.isBlank(createOrderDTO.getAddress()) ? "" : createOrderDTO.getAddress().trim()
                );
                if (StringUtil.isNotBlank(addressInfo)) {
                    cityId = Optional.ofNullable(areaListRemoteService.getAreaByAddress(addressInfo))
                            .map(areaResponse -> areaResponse.isSuccess() ? areaResponse.getData() : null)
                            .map(areaDRO -> areaDRO.getParentId())
                            .get();
                }
            }
            // 3.无法获取的情况，默认为重庆
            createOrderDTO.setCityId(cityId == null ? 500100 : cityId);
        }

        boolean isFactoryOrder = Objects.equals(GlobalConsts.YES, createOrderDTO.getFactory());
        if (isFactoryOrder) {
            throw new OmsBaseException("厂商功能已下线");
        }
        ChannelApiOrderAddDIO addDIO = this.buildNormalChannelApiOrderAddDIO(createOrderDTO);
        logger.info("OpenAPI渠道接口下单入参[{}]", JSON.toJSONString(addDIO));
        ResponseDTO<OrderAddDRO> responseDTO = channelApiOrderRemoteService.addOrder(addDIO);
        logger.info("OpenAPI渠道接口下单出参[{}]", JSON.toJSONString(responseDTO));

        if (!responseDTO.isSuccess()) {
            throw new OmsBaseException(responseDTO.getMessage());
        }

        OrderBO orderBO = new OrderBO();
        {
            Long orderId = responseDTO.getData().getOrderId();
            Order dbOrder = orderService.findOrderByKey(orderId);
            orderBO.setOrder(dbOrder);
            OrderWork dbOrderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);
            orderBO.setOrderWork(dbOrderWork);
            OrderDetail dbOrderDetail = orderDetailService.findOrderDetailByKey(orderId);
            orderBO.setOrderDetail(dbOrderDetail);
            List<OrderProduct> dbProductList = orderProductService.listOrderProductByOrderId(orderId);
            orderBO.setOrderProductList(dbProductList);
        }

        if (!isFactoryOrder) {
            OrderWork dbOrderWork = orderBO.getOrderWork();
            // 1 小时后，自动取消 (后期需增加：如该渠道设置弃单时间则取渠道弃单时间 )
            if (Objects.equals(GlobalConsts.YES, dbOrderWork.getDisableDiscard())) {
                addPrepayTimeoutCancelJob(orderBO.getOrder().getOrderId(),true);
            }

            // 渠道为人保或易家互联，且有渠道预付和未支付时，增加1小时后，如还未支付预付款，则自动取消
            if ((dbOrderWork.getChannelId() == 34113 || dbOrderWork.getChannelId() == 34537) &&
                    NumberUtil.isNotNullOrZero(dbOrderWork.getChannelPrepayAmount()) &&
                    !Objects.equals(dbOrderWork.getChannelPrepayStatus(),PayConsts.PAY_STATUS_DONE)) {
                addPrepayTimeoutCancelJob(orderBO.getOrder().getOrderId(),false);
            }
        }

        // 录单埋点
        //this.addOrderEventLog(orderBO, null);

        return orderBO;
    }


    @Override
    public void updateOrder(UpdateOrderDTO updateOrderDTO) throws OmsBaseException {
        // 获取订单ID
        Long orderId = this.getOrderId(updateOrderDTO);

        // 修改OutterId
        if (StringUtils.isNotBlank(updateOrderDTO.getOuterId())) {
            OrderWork updateOrderWork = new OrderWork();
            updateOrderWork.setOrderId(orderId);
            updateOrderWork.setWorkId(orderId);
            updateOrderWork.setOuterId(updateOrderDTO.getOuterId());
            orderWorkService.updateOrderWorkByKey(updateOrderWork);
        }

        // 修改预约时间
        if (Objects.nonNull(updateOrderDTO.getDutyTime())) {
            OrderWork updateOrderWork = new OrderWork();
            updateOrderWork.setOrderId(orderId);
            updateOrderWork.setWorkId(orderId);
            updateOrderWork.setDutyTime(updateOrderDTO.getDutyTime());
            orderWorkService.updateOrderWorkDutyTimeByKey(updateOrderWork);
        }

        {// 修改客户联系电话 & 修改客户地址
            boolean phoneIsChanged = StringUtils.isNotBlank(updateOrderDTO.getPhone());
            boolean addressIsChanged = StringUtils.isNotBlank(updateOrderDTO.getAddress());

            if (phoneIsChanged || addressIsChanged) {
                // 工单详情
                OrderDetail updateOrderDetail = new OrderDetail();
                updateOrderDetail.setDetailId(updateOrderDTO.getOrderId());

                // 修改用户的电话信息
                if (phoneIsChanged) {
                    this.changeUserMobile(updateOrderDTO.getOrderId(),updateOrderDTO.getPhone());
                    updateOrderDetail.setTelephone(updateOrderDTO.getPhone());
                }
                // 修改客户地址
                if (addressIsChanged) {
                    updateOrderDetail.setAddress(updateOrderDTO.getAddress());
                }

                orderDetailService.updateOrderDetailByKey(updateOrderDetail);
            }
        }

        // 修改渠道预付状态和可弃单状态
        if (updateOrderDTO.getDisableDiscard() != null || updateOrderDTO.getChannelPrepayStatus() != null) {
            OrderWork updateOrderWork = new OrderWork();
            updateOrderWork.setOrderId(orderId);
            updateOrderWork.setWorkId(orderId);
            updateOrderWork.setChannelPrepayStatus(updateOrderDTO.getChannelPrepayStatus());
            updateOrderWork.setDisableDiscard(updateOrderDTO.getDisableDiscard());
            orderWorkService.updateOrderWorkByKey(updateOrderWork);
        }

        // 更新外部订单信息
        if (StringUtils.isNotBlank(updateOrderDTO.getOuterData())) {
            this.saveOuterData(orderId, updateOrderDTO.getOuterData());
        }
    }


    @Override
    public void updateChannelPrepayAmount(UpdateOrderDTO updateOrderDTO) throws OmsBaseException {

        // 获取订单ID
        Long orderId = this.getOrderId(updateOrderDTO);

        OrderWork updateOrderWork = new OrderWork();
        updateOrderWork.setOrderId(orderId);
        updateOrderWork.setWorkId(orderId);
        updateOrderWork.setChannelPrepayAmount(updateOrderDTO.getChannelPrepayAmount());

        if (updateOrderWork.getChannelPrepayAmount() != null) {
            orderWorkService.updateOrderWorkByKey(updateOrderWork);
        }
    }

    @Override
    public void updateChannelOuterId(OrderQuery orderQuery) throws OmsBaseException {

        // 参数判断
        if (Objects.isNull(orderQuery) || Objects.isNull(orderQuery.getOuterId()) || orderQuery.getOuterId().isEmpty()) {
            throw new OmsBaseException("传入的参数不正确！");
        }

        // 获取订单ID
        Long orderId = this.getOrderId(orderQuery);

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);
        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException("订单不存在！");
        }

        OrderWork updateOrderWork = new OrderWork();
        updateOrderWork.setOrderId(orderWork.getOrderId());
        updateOrderWork.setWorkId(orderWork.getWorkId());
        updateOrderWork.setChannelId(orderQuery.getChannelId());
        updateOrderWork.setOuterId(orderQuery.getOuterId());
        // 获取渠道一级、二级信息
        ResponseDTO<ChannelDRO> responseDTO = channelListRemoteService.getByChannelId(orderQuery.getChannelId());
        ChannelDRO channelDRO = responseDTO.getData();
        if (responseDTO.isSuccess() && channelDRO != null) {
            updateOrderWork.setChannelName(channelDRO.getName());
            updateOrderWork.setChannelAnotherName(StringUtils.defaultString(channelDRO.getAnotherName(), ""));
            updateOrderWork.setChannelOneId(channelDRO.getPlat());
            updateOrderWork.setChannelTwoId(channelDRO.getParentId());
        }

        orderWorkService.updateChannel(updateOrderWork);
    }

    @Override
    public void payOrder(PayOrderDTO payOrderDTO) throws Exception {

        // 获取订单
        Long orderId = this.getOrderId(payOrderDTO);

        if (Objects.equals(OrderConsts.API_ORDER_PAY_TYPE_CHANNEL_PREPAID, payOrderDTO.getOrderPayType())) {

            this.saveChannelPay(orderId, payOrderDTO);

        } else {

            // 渠道二次支付
            ZsOrderPayDTO orderPayDTO = BeanMapper.map(payOrderDTO, ZsOrderPayDTO.class);
            orderPayDTO.setOrderId(orderId);
            orderPayDTO.setWorkId(orderId);

            // 是否抵扣师傅收款额
            boolean subMasterAmount = Optional.ofNullable(payOrderDTO.getSubMasterAmount()).orElse(true);
            orderPayDTO.setSubMasterAmount(subMasterAmount);

            boolean completeOrder = Optional.ofNullable(payOrderDTO.getCompleteOrder()).orElse(true);

            String lockKey = String.format("%s", payOrderDTO.getOrderId());
            DistributedLock lock = DistributedLockUtils.build(LockConsts.LOCK_ORDER_AMOUNT + lockKey, LockConsts.LOCK_VALID_TIME);
            try {
                if (lock.tryLock()) {
                    if (completeOrder) {
                        zsOrderPayBService.paySecondChannelPayAndOrderComplete(orderPayDTO);
                        payOrderDTO.setOperatorRemark(null);
                        // 完成后自动流转
                        workFlowContextBService.autoFlow(orderId, orderId);
                    }
                    else {
                        zsOrderPayBService.paySecondChannelPay(orderPayDTO);
                    }
                }
            } catch (Exception e) {
                logger.error("渠道第二次支付异常" + e.getMessage(), e);
            }finally {
                lock.unlock();
            }
        }

        // 保存 outerData
        this.saveOuterData(orderId, payOrderDTO.getOuterData());

        // 添加操作日志
        if (StringUtils.isNotBlank(payOrderDTO.getOperatorRemark())) {
            OrderLogDTO orderLogDTO = new OrderLogDTO();
            orderLogDTO.setOrderId(orderId);
            orderLogDTO.setWorkId(orderId);
            orderLogDTO.setOperatorRemark(payOrderDTO.getOperatorRemark());
            this.saveOrderLog(orderId, orderLogDTO);
        }

        payOrderDTO.setOrderId(orderId);
        payOrderDTO.setWorkId(orderId);
    }

    @Override
    public void addOrderLog(OrderLogDTO orderLogDTO) throws OmsBaseException {

        // 获取订单
        Long orderId = this.getOrderId(orderLogDTO);
        this.saveOrderLog(orderId, orderLogDTO);
        this.saveOuterData(orderId, orderLogDTO.getOuterData());
    }

    @Override
    public void cancelOrder(CancelOrderDTO cancelOrderDTO) throws OmsBaseException {
        if (cancelOrderDTO.getAgreeCancel() == null) {
            // 渠道申请取消，默认不校验是否存在待审核的取消申请 2022.07.22 by lhl
            cancelOrderDTO.setAgreeCancel(GlobalConsts.YES);
        }

        // 获取订单
        Long orderId = this.getOrderId(cancelOrderDTO);
        ZsCancelDTO zsCancelDTO = BeanMapper.map(cancelOrderDTO, ZsCancelDTO.class);
        zsCancelDTO.setOrderId(orderId);
        zsCancelDTO.setWorkId(orderId);
        zsCancelDTO.setContent(cancelOrderDTO.getRemark());
        if (!Objects.equals(GlobalConsts.YES, cancelOrderDTO.getPayTimeout())) {
            // 非超时未支付取消
            zsCancelDTO.setPayTimeout(GlobalConsts.NO);
        }

        // 处理操作人
        if (Objects.isNull(cancelOrderDTO.getOperatorId())) {
            if (Objects.equals(GlobalConsts.YES, zsCancelDTO.getPayTimeout())) {
                zsCancelDTO.setOperatorId(0L);
            }
            else {
                OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);
                zsCancelDTO.setOperatorId((long) orderWork.getChannelId());
                zsCancelDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_CHANNEL);
            }
        }

        zsNormalWorkBService.saveCancel(zsCancelDTO);

        // 保存外部数据
        this.saveOuterData(orderId, cancelOrderDTO.getOuterData());
    }

    @Override
    public void addComment(CommentDTO commentDTO) throws OmsBaseException {

        // 获取订单
        Long orderId = this.getOrderId(commentDTO);

        // 保存评价数据
        OrderCommentDTO orderCommentDTO = BeanMapper.map(commentDTO, OrderCommentDTO.class);
        orderCommentDTO.setOrderId(orderId);
        orderCommentDTO.setWorkId(orderId);
        orderCommentDTO.setType(OrderConsts.COMMENT_TYPE_THIRD);
        orderCommentBService.saveThirdComment(orderCommentDTO);

        // 根据渠道评价更新投诉等级
        // 1259	58到家APP；1322	58到家C店；1511	58到家C店独家
        // OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);
        // if (Objects.equals(orderWork.getChannelId(), 1259) || Objects.equals(orderWork.getChannelId(), 1322) || Objects.equals(orderWork.getChannelId(), 1511)) {
        //     logger.info("[{}]投诉等级更新---begin", orderId);
        //     if (orderWork != null && Objects.equals(orderWork.getComplaintStatus(), GlobalConsts.YES)) {
        //         logger.info("[{}]发现有投诉", orderId);
        //         Integer complaintLevel = OrderConsts.getComplaintLevelByScore(commentDTO.getScore());
        //         if (complaintLevel != null) {
        //             logger.info("[{}]投诉等级更新成[{}]", orderId, complaintLevel);
        //             TrackComplainLevelDIO trackComplainLevelDIO = new TrackComplainLevelDIO();
        //             trackComplainLevelDIO.setOrderId(commentDTO.getOrderId());
        //             trackComplainLevelDIO.setLevel(complaintLevel);
        //             trackComplainLevelDIO.setRemark(String.format("%s星评价修改成投诉等级%s", commentDTO.getScore(), complaintLevel));
        //             com.zmn.common.dto2.ResponseDTO<Boolean> trackComplainRemote = complainModifyRemoteService.modifyTrackComplainLevel(trackComplainLevelDIO);
        //             if (!trackComplainRemote.isSuccess()) {
        //                 logger.error("更新投诉等级失败");
        //             }
        //         }
        //     }
        // }
    }

    @Override
    public List<AvailableTimeslotsVO> queryAvailableTimeslots(AvailableTimeslotsQuery availableTimeslotsQuery) throws OmsBaseException {

        com.zmn.common.dto2.ResponseDTO<List<ProductBaseDRO>> responseDTO = null;
        try {
            ProductBaseQuery productDIO = new ProductBaseQuery();
            productDIO.setProductId(availableTimeslotsQuery.getProductId());
            responseDTO = productForeignListRemoteService.listBaseDROByQuery(productDIO);
        } catch (Exception ex) {
            logger.error(ex.getMessage());
        }

        if (responseDTO == null || !responseDTO.isSuccess() || CollectionUtil.isNullOrEmpty(responseDTO.getData())) {
            throw new OmsBaseException(StatusConsts.ERROR_DATA, "产品不存在！");
        }

        // 2、获取预约时间
        List<AvailableTimeslotsVO> timeList = Lists.newArrayList();

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        int max = 7;
        for (int i = 0; i < max; i++) {
            String day = DateUtil.toString(calendar.getTime(), DateUtil.FORMAT_DATE);

            AvailableTimeslotsVO availableTimeslotsVO = new AvailableTimeslotsVO();
            availableTimeslotsVO.setDate(day);
            OrderScheduleVO orderScheduleVO = zsOrderWorkScheduleBService.getCustomerScheduleTimes(day);
            availableTimeslotsVO.setTimeslots(orderScheduleVO.getTimes());
            timeList.add(availableTimeslotsVO);

            calendar.add(Calendar.DAY_OF_YEAR, 1);
        }

        return timeList;
    }

    /**
     * 保存为线索单
     * @param createOrderDTO
     * @param errorMsg
     * @throws ChannelFacadeException
     */
    @Override
    public void saveAsOrderClueDetail(CreateOrderDTO createOrderDTO, String errorMsg) throws ChannelFacadeException {
        if (createOrderDTO == null || createOrderDTO.getOrderClueId() == null) {
            return;
        }

        OrderClueDetail orderClueDetail = BeanMapper.map(createOrderDTO, OrderClueDetail.class);
        orderClueDetail.setClueId(createOrderDTO.getOrderClueId());
        String addressInfo = StringUtils.isNotBlank(createOrderDTO.getAddressClues())
                ? createOrderDTO.getAddressClues()
                : String.format("%s%s", createOrderDTO.getStreet(), createOrderDTO.getAddress());
        orderClueDetail.setAddressInfo(addressInfo);
        orderClueDetail.setErrorMsg(errorMsg);
        orderClueDetail.setFactoryOrderFlag(createOrderDTO.getFactory());
        orderClueDetail.setContactPhone(createOrderDTO.getTelephone());
        // 产品
        Optional.ofNullable(createOrderDTO.getOrderProductList())
                .map(list -> list.isEmpty() ? null : list.get(0))
                .ifPresent((product) -> {
                    orderClueDetail.setProductId(product.getProductId());
                    orderClueDetail.setProductNumber(product.getNumber());
                });

        // 补全产品名称
        if (orderClueDetail.getProductId() != null) {
            try {
                ProductBaseQuery productDIO = new ProductBaseQuery();
                productDIO.setProductId(orderClueDetail.getProductId());
                ResponseDTO<List<ProductBaseDRO>> productDROResp
                        = productForeignListRemoteService.listBaseDROByQuery(productDIO);
                Optional.ofNullable(productDROResp)
                        .map(ResponseDTO::getData)
                        .map(list -> list.isEmpty() ? null : list.get(0))
                        .ifPresent(productDRO -> {
                            orderClueDetail.setProductName(productDRO.getProductName());
                        });
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        }

        // 补全城市信息
        Double lng = createOrderDTO.getLongitude();
        Double lat = createOrderDTO.getLatitude();
        if (lng != null && lat != null) {
            try {
                ResponseDTO<AreaDRO> areaResponseDTO = areaListRemoteService.getAreaByLatAndLng(lng, lat);
                Optional.ofNullable(areaResponseDTO)
                        .map(ResponseDTO::getData)
                        .ifPresent(areaDRO -> {
                            orderClueDetail.setProvinceId(areaDRO.getProvinceId());
                            orderClueDetail.setProvinceName(areaDRO.getProvinceName());
                            orderClueDetail.setCityId(areaDRO.getCityId());
                            orderClueDetail.setCityName(areaDRO.getCityName());
                        });
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        }

        Integer channelId = createOrderDTO.getChannelId();
        if (channelId != null && channelId.intValue() > 0) {
            try {
                ResponseDTO<ChannelDRO> channelResp = channelListRemoteService.getByChannelId(channelId);
                Optional.ofNullable(channelResp)
                        .map(ResponseDTO::getData)
                        .ifPresent(channelDRO -> {
                            orderClueDetail.setChannelName(channelDRO.getName());
                        });
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        }

        facadeOrderClueDetailBService.saveOrderClueDetail(orderClueDetail);
    }


    /**
     * 获取订单ID
     *
     * @param orderQuery
     * @return
     * @throws OmsBaseException
     */
    private Long getOrderId(OrderQuery orderQuery) throws OmsBaseException {
        if (Objects.isNull(orderQuery.getOrderId()) && StringUtils.isBlank(orderQuery.getOuterId())) {
            throw new OmsBaseException("orderId或者outerId不能为空");
        }

        // 先根据外部订单ID查询
        if (StringUtils.isNotBlank(orderQuery.getOuterId())) {
            OrderOuterMapQuery orderOuterMapQuery = new OrderOuterMapQuery();
            orderOuterMapQuery.setChannelId(orderQuery.getChannelId());
            orderOuterMapQuery.setOuterId(orderQuery.getOuterId());
            orderOuterMapQuery.setPlat(GlobalConsts.PLAT_MARK_ZMN);
            OrderOuterMap orderOuterMap = orderOuterMapService.findByOuterId(orderOuterMapQuery);
            if (orderOuterMap != null) {
                return orderOuterMap.getOrderId();
            }
        }

        if (!NumberUtil.isNullOrZero(orderQuery.getOrderId())) {
            return orderQuery.getOrderId();
        }

        OrderWorkQuery query = new OrderWorkQuery();
        query.setId(orderQuery.getOrderId());
        query.setOuterId(orderQuery.getOuterId());
        query.setPageSize(1);
        query.setPageIndex(1);
        query.setIncludes(Arrays.asList("orderId"));
        if (orderQuery.getChannelId() != null) {
            query.setChannelIdList(Lists.newArrayList(orderQuery.getChannelId()));
        }

        List<EsOrderWork> esOrderWorkList = orderWorkListBService.listPageOrderWorkByQuery(query);
        if (CollectionUtils.isEmpty(esOrderWorkList)) {
            throw new OmsBaseException("订单不存在！");
        }

        return esOrderWorkList.get(0).getOrderId();
    }

    /**
     * 添加日志
     *
     * @param orderId
     * @param orderLogDTO
     */
    private void saveOrderLog(Long orderId, OrderLogDTO orderLogDTO) {
        if (orderLogDTO.getType() == null) {
            orderLogDTO.setType(OrderLogConsts.ORDER_LOG_TYPE_CHANNEL_REMARK);
        }

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);
        if (Objects.isNull(orderWork)) {
            return;
        }

        OrderLog orderLog = new OrderLog();
        orderLog.setOrderId(orderId);
        orderLog.setWorkId(orderId);
        orderLog.setType(orderLogDTO.getType());
        orderLog.setTypeName(OrderLogConsts.getOrderLogTypeName(orderLogDTO.getType()));
        orderLog.setBeforeStatus(orderWork.getStatus());
        orderLog.setBeforeStatusName(OrderStatusConsts.getWorkStatusName(orderWork.getStatus()));
        orderLog.setBeforeResultStatus(orderWork.getResultStatus());
        orderLog.setBeforeResultStatusName(OrderStatusConsts.getWorkResultStatusName(orderWork.getResultStatus()));
        orderLog.setAfterStatus(orderWork.getStatus());
        orderLog.setAfterStatusName(OrderStatusConsts.getWorkStatusName(orderWork.getStatus()));
        orderLog.setAfterResultStatus(orderWork.getResultStatus());
        orderLog.setAfterResultStatusName(OrderStatusConsts.getWorkResultStatusName(orderWork.getResultStatus()));
        OrderWorkLogUtils.processOrderLogOperater(orderLog, orderLogDTO);

        StringBuilder sb = new StringBuilder();

        if (StringUtils.isNotBlank(orderLogDTO.getOperatorRemark())) {
            sb.append(orderLogDTO.getOperatorRemark());
        }

        if (StringUtils.isNotBlank(orderLogDTO.getOperatorLogRemark())) {
            sb.append(orderLogDTO.getOperatorLogRemark());
        }

        orderLog.setContent(sb.toString());
        orderLogBService.save(orderLog);
    }

    private void saveOuterData(Long orderId, String outerData) {

        // 保存 outerData
        if (StringUtils.isNotBlank(outerData)) {
            OrderExtend orderExtend = new OrderExtend();
            orderExtend.setExtId(orderId);
            orderExtend.setOuterData(outerData);
            orderExtendService.updateOrderExtend(orderExtend);
        }
    }

    /**
     * 保存渠道二次支付金额信息
     *
     * @param payOrderDTO
     */
    @Deprecated
    public void saveChannelSecondPay(PayOrderDTO payOrderDTO) throws Exception {
        Long orderId = payOrderDTO.getOrderId();
        OrderWork dbOrderWork = orderWorkService.findOrderWorkByKey(payOrderDTO.getOrderId(), payOrderDTO.getOrderId());
        Integer fristPayAmount = Optional.ofNullable(dbOrderWork.getChannelPrepayAmount()).orElse(0);
        Integer secondPayAmount = payOrderDTO.getPayAmount();
        payOrderDTO.setPayAmount(fristPayAmount + secondPayAmount);

        saveChannelPay(orderId, payOrderDTO);

        // 添加操作日志
        OrderLogDTO orderLogDTO = new OrderLogDTO();
        orderLogDTO.setOrderId(orderId);
        orderLogDTO.setWorkId(orderId);

        StringBuilder builder = new StringBuilder();
        if (payOrderDTO.getOperatorRemark() != null) {
            builder.append(payOrderDTO.getOperatorRemark());
        }

        builder.append("订单已预付").append(String.format("%.2f", AmountUtil.fen2Yuan(fristPayAmount))).append("元，")
                .append("二次预付").append(String.format("%.2f", AmountUtil.fen2Yuan(secondPayAmount))).append("元；");
        orderLogDTO.setOperatorRemark(builder.toString());

        this.saveOrderLog(orderId, orderLogDTO);

    }

    // 设置日志参数
    private void setLogParam(OrderQuery orderDto, OmsOperator dto) {
        // 处理操作人
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderDto.getOrderId(), orderDto.getWorkId());
        dto.setOperatorId((long) orderWork.getChannelId());
        dto.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_CHANNEL);
        dto.setPlat(orderWork.getPlat());
        dto.setOperator(orderDto.getMasterName() == null ? orderWork.getMasterName() : orderDto.getMasterName());
    }


    /**
     * 订单预付
     *
     * @param orderId
     * @param payOrderDTO
     * @throws Exception
     */
    private void saveChannelPay(Long orderId, PayOrderDTO payOrderDTO) throws Exception {

        // 改预付和预付状态
        OrderWork updateAmount = new OrderWork();
        updateAmount.setOrderId(orderId);
        updateAmount.setWorkId(orderId);
        updateAmount.setChannelPrepayStatus(PayConsts.PAY_STATUS_DONE);
        updateAmount.setChannelPrepayAmount(payOrderDTO.getPayAmount());
        updateAmount.setDisableDiscard(GlobalConsts.NO);
        orderWorkAmountService.updatePayStatusChannelPrepay(updateAmount);

        // 更新到优惠信息 Xiewenbing 2020.04.29
        if (NumberUtil.isNotNullOrZero(payOrderDTO.getDiscountAmount())) {
            AddDiscountDTO addDiscountDTO = new AddDiscountDTO();
            addDiscountDTO.setOrderId(orderId);
            addDiscountDTO.setWorkId(orderId);
            addDiscountDTO.setAmount(payOrderDTO.getDiscountAmount());
            addDiscountDTO.setDiscountUserName("系统");
            orderDiscountBService.channelDiscount(addDiscountDTO);
        }

        // 校验原价是否小于预付
        OrderWork dbOrderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);
        if (!NumberUtil.isNullOrZero(dbOrderWork.getOriginalAmount())) {
            ValidateWorkAmountDTO validateWorkAmountDTO = new ValidateWorkAmountDTO();
            validateWorkAmountDTO.setOrderId(orderId);
            validateWorkAmountDTO.setWorkId(orderId);
            validateWorkAmountDTO.setOriginalAmount(dbOrderWork.getOriginalAmount());
            boolean validateOriginalAmount = orderWorkAmountBService.validateWorkAmount(validateWorkAmountDTO);

            // 更新应收、工程师收款金额
            if (validateOriginalAmount) {
                ZsUpdateChannelPrepayAmountDTO channelPrepayAmountDTO = new ZsUpdateChannelPrepayAmountDTO();
                channelPrepayAmountDTO.setOperatorRemark(payOrderDTO.getOperatorRemark());
                channelPrepayAmountDTO.setOperatorLogRemark("渠道支付：" + MoneyUtil.parseToYuan(payOrderDTO.getPayAmount()));
                channelPrepayAmountDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_CHANNEL);
                channelPrepayAmountDTO.setOperatorId((long) GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
                channelPrepayAmountDTO.setOperator("系统");
                channelPrepayAmountDTO.setOrderId(orderId);
                channelPrepayAmountDTO.setWorkId(orderId);
                channelPrepayAmountDTO.setChannelPrepayAmount(payOrderDTO.getPayAmount());
                zsNormalMasterWorkBService.saveChannelPrepayAmountPay(channelPrepayAmountDTO);
            }

            // 原价验证失败，删除工程师收款、订单收入、优惠
            if (!validateOriginalAmount) {
                orderWorkAmountService.deleteOriginalAmount(orderId, orderId);
            }
        }
    }

    /**
     * 天猫无忧购的清洗单，将原价和渠道预付的差额设置为渠道优惠（渠道预付=订单收入）。
     * 当原价和渠道预付有差额时（原价大于渠道预付），系统默认会将差额设置为工程师收款金额，
     * 需要修改这个设置，将工程师收款金额置为0，并将工程师收款金额保存到优惠金额中，将工单的应收
     * 设置为等于渠道预付款
     */
    private void changeTaobaoCleanOrderMasterAmount2DiscountAmount(OrderWork orderWork) throws OmsBaseException {
        int discountAmount = orderWork.getOriginalAmount() - orderWork.getChannelPrepayAmount();
        if (discountAmount > 0) {
            AddDiscountDTO addDiscountDTO = new AddDiscountDTO();
            addDiscountDTO.setOrderId(orderWork.getOrderId());
            addDiscountDTO.setWorkId(orderWork.getWorkId());
            addDiscountDTO.setAmount(discountAmount);
            addDiscountDTO.setDiscountUserName("系统");
            orderDiscountBService.channelDiscount(addDiscountDTO);
        }
    }

    /**
     * 获取默认服务项
     * @param getServiceItemDTO
     * @return
     */
    private List<OrderServiceItem> listDefaultServiceItem(GetServiceItemDTO getServiceItemDTO){
        CheckQuotationTypeOrderDTO build = CheckQuotationTypeOrderDTO
                .builder()
                .sourceType(getServiceItemDTO.getSourceType())
                .channelId(getServiceItemDTO.getChannelId())
                .bizType(getServiceItemDTO.getBizType())
                .cityId(getServiceItemDTO.getCityId())
                .productId(getServiceItemDTO.getProductId())
                .platWork(getServiceItemDTO.getPlatWork())
                .build();
        Integer servItemType = servItemBService.getServItemType(build);

        ServiceItemQueryDTO serviceItemQueryDTO = ServiceItemQueryDTO
                .builder()
                .servItemType(servItemType)
                .general(GlobalConsts.YES)
                .channelId(getServiceItemDTO.getChannelId())
                .productId(getServiceItemDTO.getProductId())
                .bizType(getServiceItemDTO.getBizType())
                .cityId(getServiceItemDTO.getCityId())
                .build();
        ResponseDTO<ServiceItemResultDTO> serviceItem = servItemBService.getServiceItem(serviceItemQueryDTO);

        List<OrderServiceItem> defaultServiceItemLists = Lists.newArrayList();
        // 服务项数据为空
        if (!serviceItem.isSuccess() || Objects.isNull(serviceItem.getData())) {
            logger.info(serviceItem.getMessage());
            return defaultServiceItemLists;
        }

        ServiceItemResultDTO defaultItem = serviceItem.getData();
        int productNumer = Optional.ofNullable(getServiceItemDTO.getProductNumber()).orElse(1);
        for (int i = 0; i < productNumer; i++) {
            OrderServiceItem orderServiceItem = new OrderServiceItem();
            orderServiceItem.setProductId(getServiceItemDTO.getProductId());
            orderServiceItem.setItemPrice(defaultItem.getPrice());
            orderServiceItem.setNumber(1);
            orderServiceItem.setTotalPrice(defaultItem.getPrice());
            orderServiceItem.setServItemId(defaultItem.getItemId());
            orderServiceItem.setServItemName(defaultItem.getItemName());
            orderServiceItem.setServItemGroupId(Optional.ofNullable(defaultItem.getItemCategId()).orElse(0));
            orderServiceItem.setServItemGroupName(defaultItem.getItemCategName());
            defaultServiceItemLists.add(orderServiceItem);
        }
        logger.info("返回默认服务项列表[{}]", defaultServiceItemLists);
        return defaultServiceItemLists;
    }

    /**
     * 修改用户电话 - xiewenbing 2020-05-29
     *
     * @param orderId
     * @param userMobile
     */
    private void changeUserMobile(Long orderId,String userMobile) {

        logger.info("修改订单用户电话，订单id:[{}]，电话:[{}]",orderId,userMobile);
        if (NumberUtil.isNullOrZero(orderId) || StringUtil.isBlank(userMobile)) {
            return;
        }

        // 获取原有的用户电话
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(orderId);
        if (Objects.isNull(orderDetail)) {
            return;
        }

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId,orderId);
        if (Objects.isNull(orderWork)) {
            return;
        }

        if (NumberUtil.isNullOrZero(orderWork.getUserId())) {

            Integer channelId = orderWork.getChannelId();

            // 根据入口判断是否为已登录状态
            boolean isRegisterUserCenter = (OrderConsts.LOGIN_ENTRANCE_LIST.contains(orderWork.getReceiveEntranceId()) && StringUtil.isMobile(orderDetail.getTelephone())) ||
                    (OrderConsts.LOGIN_CHANNEL_LIST.contains(channelId) && Objects.equals(orderWork.getInputType(), OrderConsts.ORDER_INPUT_TYPE_API));

            ResponseDTO<ChannelDRO> channelResponseDTO = channelListRemoteService.getByChannelId(channelId);
            ChannelDRO channelDRO = channelResponseDTO.getData();

            ResponseDTO<Long> responseDTO ;
            // 通过电话注册用户
            if (isRegisterUserCenter) {
                // 登录状态 ucc创建用户
                UserRegisterByMobileNoCaptchaDIO userRegisterByMobileNoCaptchaDIO = new UserRegisterByMobileNoCaptchaDIO();
                userRegisterByMobileNoCaptchaDIO.setMobile(userMobile);
                userRegisterByMobileNoCaptchaDIO.setChannelId(channelId);
                userRegisterByMobileNoCaptchaDIO.setChannelName(channelDRO.getName());
                userRegisterByMobileNoCaptchaDIO.setPlat(orderWork.getPlat());
                userRegisterByMobileNoCaptchaDIO.setEntrance(NumberUtil.isNullOrZero(orderWork.getReceiveEntranceId()) ? GateTypeConsts.GATE_API_NORM : orderWork.getReceiveEntranceId());
                userRegisterByMobileNoCaptchaDIO.setNickName(orderDetail.getUserName());
                userRegisterByMobileNoCaptchaDIO.setOperator("系统");
                userRegisterByMobileNoCaptchaDIO.setOperatorId(Long.valueOf(channelId));
                logger.debug("调用uuc创建用户入参，userRegisterDIO：{}", JSONObject.toJSONString(userRegisterByMobileNoCaptchaDIO));

                // 修改调用uuc接口  xiewenbing  2020-11-16
                responseDTO = userRegisterRemoteService.registerByMobileNoCaptcha(userRegisterByMobileNoCaptchaDIO);
                logger.debug("调用uuc创建用户出参，userResponseDTO：{}，orderId：{}", JSONObject.toJSONString(responseDTO),orderWork.getOrderId());

            } else {
                // 未登录状态创建临时用户
                UserTempRegisterDIO userTempRegisterDIO = new UserTempRegisterDIO();
                userTempRegisterDIO.setGender(orderDetail.getGender());
                userTempRegisterDIO.setPlat(orderWork.getPlat());
                userTempRegisterDIO.setChannelId(channelId);
                userTempRegisterDIO.setChannelName(channelDRO.getName());
                userTempRegisterDIO.setEntrance(NumberUtil.isNullOrZero(orderWork.getReceiveEntranceId()) ? GateTypeConsts.GATE_API_NORM : orderWork.getReceiveEntranceId());
                userTempRegisterDIO.setNickName(FilterUtil.replaceSpeChar(StringUtils.defaultString(orderDetail.getUserName())));
                userTempRegisterDIO.setOperator("系统");
                userTempRegisterDIO.setOperatorId(Long.valueOf(channelId));
                logger.debug("调用uuc创建临时用户入参，userRegisterDIO：{} ", JSONObject.toJSONString(userTempRegisterDIO));

                // 修改调用uuc接口  xiewenbing  2020-11-16
                responseDTO = userRegisterRemoteService.registerTempUser(userTempRegisterDIO);
                logger.debug("调用uuc创建临时用户出参，userResponseDTO：{}，orderId：{}", JSONObject.toJSONString(responseDTO),orderWork.getOrderId());

            }

            logger.info("通过电话注册用户，电话：[{}]，结果：[{}]", userMobile,responseDTO.isSuccess() ? "success" : "failed");

            if (responseDTO.isSuccess()) {

                OrderWork updateOrderWork = new OrderWork();
                updateOrderWork.setOrderId(orderId);
                updateOrderWork.setWorkId(orderId);
                updateOrderWork.setUserId(responseDTO.getData());

                orderWorkService.updateOrderWorkByKey(updateOrderWork);
            }

        } else {

            // 修改用户电话 - uuc接口  xiewenbing  2020-11-16
            com.zmn.common.dto2.ResponseDTO responseDTO = userModifyRemoteService.modifyPhoneByUserId(orderWork.getUserId(),userMobile);
            logger.info("修改用户电话，用户id：[{}]，新电话：[{}]，原有电话：[{}],结果：[{}]", orderWork.getUserId(), userMobile, orderDetail.getTelephone(),
                    responseDTO.isSuccess() ? "success" : "failed");
            if (responseDTO.isSuccess()) {
                return;
            }

            // 失败可能是已经注册了，根据电话查找并重新设置工单的用户id
            UserMobilePlatQuery userMobilePlatQuery = new UserMobilePlatQuery();
            userMobilePlatQuery.setPlat(orderWork.getPlat());
            userMobilePlatQuery.setIsSensitive(Boolean.FALSE);
            userMobilePlatQuery.setMobile(userMobile);
            ResponseDTO<UserBaseDRO> userResponseDTO = userListRemoteService.getMajorUserByMobileAndPlat(userMobilePlatQuery);
            if (!userResponseDTO.isSuccess()) {
                return;
            }

            OrderWork updateOrderWork = new OrderWork();
            updateOrderWork.setOrderId(orderId);
            updateOrderWork.setWorkId(orderId);
            updateOrderWork.setUserId(userResponseDTO.getData().getUserId());

            orderWorkService.updateOrderWorkByKey(updateOrderWork);
        }
    }

    /**
     * 添加超时取消任务
     *
     * @param orderId
     */
    void addPrepayTimeoutCancelJob(Long orderId,boolean prepayTimeout) {

        // 预付超时或渠道预付超时
        String taskId = prepayTimeout ? TaskConsts.TASK_ID_PREPAY_TIMEOUT_CANCEL : TaskConsts.TASK_ID_CHANNEL_PAY_TIMEOUT_CANCEL;

        Job job = new Job();
        job.setTaskId( taskId + ":" + orderId);
        job.setParam(TaskManager.SHARD_FIELD, taskId);
        job.setParam("orderId", orderId.toString());
        Date date = DateUtil.addMinute(DateUtil.getNow(), OrderConsts.ORDER_PREPAY_TIMEOUT_CANCEL_MINUTES);
        taskManager.submitTask(job, -1, DateUtil.dateFormatToString(date, DateUtil.FORMAT_DEFAULT));
    }

    /**
     * 新增订单埋点
     *
     * @param orderBO
     * @param omsBaseOperator
     */
    private void addOrderEventLog(OrderBO orderBO, OmsBaseOperator omsBaseOperator) {
        try {
            OrderWork orderWork = orderBO.getOrderWork();
            OrderDetail orderDetail = orderBO.getOrderDetail();
            List<OrderProduct> orderProductList = orderBO.getOrderProductList();
            OrderProduct orderProduct = orderProductList.get(0);
            final String site = "zmn-oms-api";

            AddOrderEventLogItem eventLogItem = new AddOrderEventLogItem();
            eventLogItem.setSite(site);
            eventLogItem.setBizId(String.valueOf(orderWork.getOrderId()));
            eventLogItem.setOrderId(String.valueOf(orderWork.getOrderId()));
            if (NumberUtil.isNotNullOrZero(orderProduct.getProductId())) {
                eventLogItem.setProductId(String.valueOf(orderProduct.getProductId()));
                eventLogItem.setProductName(orderProduct.getProductName());
            } else {
                eventLogItem.setProductId(String.valueOf(orderProduct.getShowProductId()));
                eventLogItem.setProductName(orderProduct.getShowProductName());
            }
            eventLogItem.setChannelId(String.valueOf(orderWork.getChannelId()));
            eventLogItem.setOrderChannelId(String.valueOf(orderWork.getChannelId()));
            eventLogItem.setSourceChannelId(String.valueOf(orderWork.getSourceChannelId()));
            eventLogItem.setLng(Objects.isNull(orderDetail.getLongitude()) ? "" : String.valueOf(orderDetail.getLongitude()));
            eventLogItem.setLat(Objects.isNull(orderDetail.getLatitude()) ? "" : String.valueOf(orderDetail.getLatitude()));

            DeviceLogItem deviceLogItem = new DeviceLogItem();
            if (Objects.nonNull(omsBaseOperator)) {
                deviceLogItem.setIp(omsBaseOperator.getIp());
            }

            EntryLogItem entryLogItem = new EntryLogItem();
            entryLogItem.setEntryType(String.valueOf(GateTypeConsts.GATE_TYPE_API));
            entryLogItem.setEntry(String.valueOf(GateTypeConsts.GATE_API_NORM));

            AddUserOperationLogRequest<AddOrderEventLogItem> request = new AddUserOperationLogRequest<>();
            request.setEntry(entryLogItem);
            request.setDevice(deviceLogItem);
            request.setEvent(eventLogItem);
            request.setClientName(site);

            logClient.addAddOrderEventLog(request);
        } catch (Exception e) {
            logger.error("addOrderEventLog error：", e);
        }
    }

    // region 封装统一录单对象
    /**
     * 录入厂商单
     * @param createOrderDTO
     * @return
     * @throws OmsBaseException
     */
    private ChannelApiOrderAddDIO buildFactoryChannelApiOrderAddDIO(CreateOrderDTO createOrderDTO) throws OmsBaseException {
        throw new OmsBaseException("厂商服务已下线");
        /*ChannelApiOrderAddDIO orderAddDIO = BeanMapper.map(createOrderDTO, ChannelApiOrderAddDIO.class);
        StringJoiner logRemarkBuilder = new StringJoiner("；");

        if (StringUtil.isNotBlank(createOrderDTO.getOperatorLogRemark())) {
            logRemarkBuilder.add(createOrderDTO.getOperatorLogRemark());
        }

        if (StringUtil.isNotBlank(createOrderDTO.getRemark())) {
            logRemarkBuilder.add(createOrderDTO.getRemark());
        }

        // 校验厂商信息
        FactoryBaseDRO factoryBaseDRO = null;
        try {
            ResponseDTO<FactoryBaseDRO> factoryResponseDTO = factoryListRemoteService
                    .getFactoryByChannelId(createOrderDTO.getChannelId());

            factoryBaseDRO = Optional.ofNullable(factoryResponseDTO.getData())
                    .orElseThrow(() -> new OmsBaseException(StatusConsts.ERROR_DATA, "渠道ID有误，未找到对应厂商！"));
            orderAddDIO.setFactoryId(factoryBaseDRO.getFcId());
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            if (e instanceof OmsBaseException) {
                throw (OmsBaseException)e;
            }
            else {
                throw new OmsBaseException(StatusConsts.ERROR_DATA, "查找厂商信息失败！");
            }
        }

        {// 客户信息
            UserDIO userDIO = BeanMapper.map(createOrderDTO, UserDIO.class);
            orderAddDIO.setUserDIO(userDIO);

            userDIO.setUserName(
                    StringUtils.isNotBlank(userDIO.getContactName())
                            ? userDIO.getContactName()
                            : "未知"
            );
            // 日志记录经纬度信息
            if (userDIO.getLongitude() != null && userDIO.getLatitude() != null) {
                logRemarkBuilder.add(
                        String.format("经纬度：%s,%s", userDIO.getLongitude(), userDIO.getLatitude())
                );
            }
        }
        {// 订单信息
            OrderBaseInfo orderBaseInfo = BeanMapper.map(createOrderDTO, OrderBaseInfo.class);
            orderAddDIO.setOrderBaseInfo(orderBaseInfo);

            orderBaseInfo.setType(OrderConsts.ORDER_TYPE_NEW);
            orderBaseInfo.setReceiveEntranceId(GateTypeConsts.GATE_API_CUSTOM_MADE);
            orderBaseInfo.setReceiverManner(OrderConsts.RECEIVE_MANNER_API);
            // 默认平台
            orderBaseInfo.setPlat(
                    Optional.ofNullable(orderBaseInfo.getPlat()).orElse(GlobalConsts.PLAT_MARK_YEYX)
            );
            // 默认api录入
            orderBaseInfo.setInputType(
                    Optional.ofNullable(orderBaseInfo.getInputType()).orElse(OrderConsts.ORDER_INPUT_TYPE_API)
            );
            // 判断是否保内
            orderBaseInfo.setBizType(
                    Optional.ofNullable(orderBaseInfo.getBizType()).orElse(com.zmn.consts.GlobalConsts.BIZ_TYPE_F)
            );
            // 渠道id
            orderBaseInfo.setChannelId(Objects.isNull(factoryBaseDRO) ? null : factoryBaseDRO.getChannelId());
        }
        {// 产品信息
            OrderProductDIO orderProductDIO = BeanMapper.map(createOrderDTO.getOrderProductList().get(0), OrderProductDIO.class);
            orderAddDIO.setOrderProductList(Lists.newArrayList(orderProductDIO));

            if (NumberUtil.isNullOrZero(orderProductDIO.getNumber())) {
                orderProductDIO.setNumber(1);
            }
        }
        {// 渠道扩展信息
            ChannelApiExtraData extraData = BeanMapper.map(createOrderDTO, ChannelApiExtraData.class);
            orderAddDIO.setChannelApiExtraData(extraData);
        }



        // 通过产品查询服务分类
        try {
            OrderProductDIO orderProductDIO = orderAddDIO.getOrderProductList().get(0);
            orderAddDIO.setServCategId(null);

            Integer productId = orderProductDIO.getShowProductId();
            if (NumberUtil.isNullOrZero(productId)) {
                productId = orderProductDIO.getProductId();
            }
            // 修正已失效产品ID lhl-2021.01.08
            productId = ProductIdUtil.getNewProductId(productId);
            if (!NumberUtil.isNullOrZero(productId)) {
                ProductBaseQuery productDIO = new ProductBaseQuery();
                productDIO.setProductId(productId);
                com.zmn.common.dto2.ResponseDTO<List<ProductBaseDRO>> productDROResp = productForeignListRemoteService
                        .listBaseDROByQuery(productDIO);
                Optional.ofNullable(productDROResp.getData())
                        .map(list -> list.get(0))
                        .ifPresent(productBaseDRO -> {
                            orderAddDIO.setServCategId(productBaseDRO.getServCategId());

                            // 修正是否是前台产品ID
                            if (Objects.equals(GlobalConsts.YES, productBaseDRO.getShowType())) {
                                orderProductDIO.setShowProductId(productBaseDRO.getProductId());
                                orderProductDIO.setProductId(0);
                            }
                            else {
                                orderProductDIO.setProductId(productBaseDRO.getProductId());
                            }
                        });
            }

            if (orderAddDIO.getServCategId() == null) {
                orderProductDIO.setProductId(OrderConsts.CHANNEL_DISABLED_PRODUCT_ID);
                orderAddDIO.setServCategId(GlobalConsts.SERV_CATEG_REPAIR);
            }
        } catch (Exception e) {
            throw new OmsBaseException("产品不存在", e);
        }

        // 操作人为渠道
        orderAddDIO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_CHANNEL);
        orderAddDIO.setOperatorId((long) createOrderDTO.getChannelId());
        orderAddDIO.setOperator("系统");
        if (logRemarkBuilder.length() > 1) {
            orderAddDIO.setOperatorRemark(logRemarkBuilder.toString());
        }

        return orderAddDIO;*/
    }

    /**
     * 录入厂商单
     * @param createOrderDTO
     * @return
     * @throws OmsBaseException
     */
    private ChannelApiOrderAddDIO buildFactoryChannelApiOrderAddDIO(com.zmn.oms.model.dto.order.open.CreateOrderDTO createOrderDTO)
            throws OmsBaseException {
        throw new OmsBaseException("厂商服务已下线");
        /*ChannelApiOrderAddDIO orderAddDIO = new ChannelApiOrderAddDIO();
        StringJoiner logRemarkBuilder = new StringJoiner("；");

        if (StringUtil.isNotBlank(createOrderDTO.getRemark())) {
            logRemarkBuilder.add(createOrderDTO.getRemark());
        }

        // 校验厂商信息
        FactoryBaseDRO factoryBaseDRO = null;
        try {
            ResponseDTO<FactoryBaseDRO> factoryResponseDTO = factoryListRemoteService
                    .getFactoryByChannelId(createOrderDTO.getChannelId());

            factoryBaseDRO = Optional.ofNullable(factoryResponseDTO.getData())
                    .orElseThrow(() -> new OmsBaseException(StatusConsts.ERROR_DATA, "渠道ID有误，未找到对应厂商！"));
            orderAddDIO.setFactoryId(factoryBaseDRO.getFcId());
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            if (e instanceof OmsBaseException) {
                throw (OmsBaseException)e;
            }
            else {
                throw new OmsBaseException(StatusConsts.ERROR_DATA, "查找厂商信息失败！");
            }
        }

        {// 客户信息
            UserDIO userDIO = BeanMapper.map(createOrderDTO, UserDIO.class);
            orderAddDIO.setUserDIO(userDIO);

            userDIO.setUserName(
                    StringUtils.isNotBlank(userDIO.getContactName())
                            ? userDIO.getContactName()
                            : "未知"
            );
            // 日志记录经纬度信息
            if (userDIO.getLongitude() != null && userDIO.getLatitude() != null) {
                logRemarkBuilder.add(
                        String.format("经纬度：%s,%s", userDIO.getLongitude(), userDIO.getLatitude())
                );
            }
        }
        {// 订单信息
            OrderBaseInfo orderBaseInfo = BeanMapper.map(createOrderDTO, OrderBaseInfo.class);
            orderAddDIO.setOrderBaseInfo(orderBaseInfo);

            orderBaseInfo.setType(OrderConsts.ORDER_TYPE_NEW);
            orderBaseInfo.setReceiveEntranceId(GateTypeConsts.GATE_API_TMALL);
            orderBaseInfo.setReceiverManner(OrderConsts.RECEIVE_MANNER_API);
            // 默认平台
            orderBaseInfo.setPlat(
                    Optional.ofNullable(orderBaseInfo.getPlat()).orElse(GlobalConsts.PLAT_MARK_YEYX)
            );
            // 默认api录入
            orderBaseInfo.setInputType(
                    Optional.ofNullable(orderBaseInfo.getInputType()).orElse(OrderConsts.ORDER_INPUT_TYPE_API)
            );
            // 判断是否保内
            orderBaseInfo.setBizType(
                    Objects.equals(createOrderDTO.getFacInWarranty(), GlobalConsts.YES)
                            ? com.zmn.consts.GlobalConsts.BIZ_TYPE_F
                            : com.zmn.consts.GlobalConsts.BIZ_TYPE_C
            );
            //渠道id
            orderBaseInfo.setChannelId(Objects.isNull(factoryBaseDRO) ? null : factoryBaseDRO.getChannelId());
        }
        {// 产品信息
            OrderProductDIO orderProductDIO = BeanMapper.map(createOrderDTO, OrderProductDIO.class);
            orderAddDIO.setOrderProductList(Lists.newArrayList(orderProductDIO));

            orderProductDIO.setNumber(
                    NumberUtil.isNullOrZero(createOrderDTO.getProductCount())
                            ? 1
                            : createOrderDTO.getProductCount()
            );
        }
        {// 渠道扩展信息
            ChannelApiExtraData extraData = BeanMapper.map(createOrderDTO, ChannelApiExtraData.class);
            orderAddDIO.setChannelApiExtraData(extraData);

            extraData.setOuterId(createOrderDTO.getThirdOrderId());
            extraData.setOuterData(createOrderDTO.getOuterJsonData());
            if (StringUtils.isNotBlank(createOrderDTO.getExtraData())) {
                extraData.setExtraData(createOrderDTO.getExtraData());
            }
            if (StringUtils.isNotBlank(createOrderDTO.getThirdOrderId2())) {
                extraData.setExtOuterId(createOrderDTO.getThirdOrderId2());
            }
        }

        // 通过产品查询服务分类
        try {
            OrderProductDIO orderProductDIO = orderAddDIO.getOrderProductList().get(0);
            orderAddDIO.setServCategId(null);

            Integer productId = orderProductDIO.getProductId();
            // 修正已失效产品ID lhl-2021.01.08
            productId = ProductIdUtil.getNewProductId(productId);
            if (!NumberUtil.isNullOrZero(productId)) {
                ProductBaseQuery productDIO = new ProductBaseQuery();
                productDIO.setProductId(productId);
                com.zmn.common.dto2.ResponseDTO<List<ProductBaseDRO>> productDROResp = productForeignListRemoteService
                        .listBaseDROByQuery(productDIO);
                Optional.ofNullable(productDROResp.getData())
                        .map(list -> list.get(0))
                        .ifPresent(productBaseDRO -> {
                            orderAddDIO.setServCategId(productBaseDRO.getServCategId());

                            // 修正是否是前台产品ID
                            if (Objects.equals(GlobalConsts.YES, productBaseDRO.getShowType())) {
                                orderProductDIO.setShowProductId(productBaseDRO.getProductId());
                                orderProductDIO.setProductId(0);
                            }
                            else {
                                orderProductDIO.setProductId(productBaseDRO.getProductId());
                            }
                        });
            }

            if (orderAddDIO.getServCategId() == null) {
                orderProductDIO.setProductId(OrderConsts.CHANNEL_DISABLED_PRODUCT_ID);
                orderAddDIO.setServCategId(GlobalConsts.SERV_CATEG_REPAIR);
            }
        } catch (Exception e) {
            throw new OmsBaseException("产品不存在", e);
        }

        // 操作人为渠道
        orderAddDIO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_CHANNEL);
        orderAddDIO.setOperatorId((long) createOrderDTO.getChannelId());
        orderAddDIO.setOperator("系统");
        if (logRemarkBuilder.length() > 1) {
            orderAddDIO.setOperatorRemark(logRemarkBuilder.toString());
        }

        return orderAddDIO;*/
    }

    /**
     * 录入普通单
     * @param createOrderDTO
     * @return
     * @throws OmsBaseException
     */
    private ChannelApiOrderAddDIO buildNormalChannelApiOrderAddDIO(CreateOrderDTO createOrderDTO) throws OmsBaseException {
        ChannelApiOrderAddDIO orderAddDIO = new ChannelApiOrderAddDIO();
        StringJoiner logRemarkBuilder = new StringJoiner("；");

        if (StringUtil.isNotBlank(createOrderDTO.getOperatorLogRemark())) {
            logRemarkBuilder.add(createOrderDTO.getOperatorLogRemark());
        }
        if (StringUtil.isNotBlank(createOrderDTO.getRemark())) {
            logRemarkBuilder.add(createOrderDTO.getRemark());
        }

        if (StringUtil.isNotBlank(createOrderDTO.getRequestId())) {
            orderAddDIO.setRequestId(createOrderDTO.getRequestId());
        }

        {// 客户信息
            UserDIO userDIO = BeanMapper.map(createOrderDTO, UserDIO.class);
            orderAddDIO.setUserDIO(userDIO);

            userDIO.setUserName(
                    StringUtils.isNotBlank(userDIO.getContactName())
                            ? userDIO.getContactName()
                            : "未知"
            );
            // 日志记录经纬度信息
            if (userDIO.getLongitude() != null && userDIO.getLatitude() != null) {
                logRemarkBuilder.add(
                        String.format("经纬度：%s,%s", userDIO.getLongitude(), userDIO.getLatitude())
                );
            }
        }
        {// 订单信息
            OrderBaseInfo orderBaseInfo = BeanMapper.map(createOrderDTO, OrderBaseInfo.class);
            orderAddDIO.setOrderBaseInfo(orderBaseInfo);

            orderBaseInfo.setType(
                    createOrderDTO.getOriginalId() != null ? OrderConsts.ORDER_TYPE_REWORK : OrderConsts.ORDER_TYPE_NEW
            );
            orderBaseInfo.setReceiveEntranceId(
                    (createOrderDTO.getProxyFromType() == null
                            || Objects.equals(1, createOrderDTO.getProxyFromType())) // 渠道来源 1=API
                            ? GateTypeConsts.GATE_API_CUSTOM_MADE
                            : Objects.equals(2, createOrderDTO.getProxyFromType())   // 渠道来源 2=H5
                            ? GateTypeConsts.GATE_WECHAT_H5_OLD
                            : createOrderDTO.getProxyFromType()
            );
            orderBaseInfo.setReceiverManner(Objects.equals(createOrderDTO.getInputType(),OrderConsts.ORDER_INPUT_TYPE_MANUAL) ?
                    OrderConsts.RECEIVE_MANNER_MANUAL : OrderConsts.RECEIVE_MANNER_API);
            // 默认平台
            orderBaseInfo.setPlat(
                    Optional.ofNullable(orderBaseInfo.getPlat()).orElse(GlobalConsts.PLAT_MARK_ZMN)
            );
            // 默认api录入
            orderBaseInfo.setInputType(
                    Optional.ofNullable(orderBaseInfo.getInputType()).orElse(OrderConsts.ORDER_INPUT_TYPE_API)
            );
            // 默认业务类型为C端订单
            orderBaseInfo.setBizType(
                    Optional.ofNullable(orderBaseInfo.getBizType()).orElse(com.zmn.consts.GlobalConsts.BIZ_TYPE_C)
            );
        }
        {// 产品信息
            OrderProductDIO orderProductDIO = BeanMapper.map(createOrderDTO.getOrderProductList().get(0), OrderProductDIO.class);
            orderAddDIO.setOrderProductList(Lists.newArrayList(orderProductDIO));

            if (NumberUtil.isNullOrZero(orderProductDIO.getNumber())) {
                orderProductDIO.setNumber(1);
            }
        }
        {// 渠道扩展信息
            ChannelApiExtraData extraData = BeanMapper.map(createOrderDTO, ChannelApiExtraData.class);
            orderAddDIO.setChannelApiExtraData(extraData);

            Integer channelPrepayStatus = Optional.ofNullable(extraData.getChannelPrepayStatus())
                    .orElse(PayConsts.PAY_STATUS_NONE);
            Integer disableDiscard = Optional.ofNullable(extraData.getDisableDiscard())
                    .orElseGet(() -> {
                        boolean hasChannelPrepayAmount = NumberUtil.isNotNullOrZero(extraData.getChannelPrepayAmount());
                        boolean isPaied = Objects.equals(channelPrepayStatus, PayConsts.PAY_STATUS_DONE);
                        return (hasChannelPrepayAmount && isPaied) ? GlobalConsts.NO : GlobalConsts.YES;
                    });
            extraData.setChannelPrepayStatus(channelPrepayStatus);
            extraData.setDisableDiscard(disableDiscard);
        }

        // 通过产品查询服务分类
        try {
            OrderProductDIO orderProductDIO = orderAddDIO.getOrderProductList().get(0);
            orderAddDIO.setServCategId(null);

            Integer productId = orderProductDIO.getShowProductId();
            if (NumberUtil.isNullOrZero(productId)) {
                productId = orderProductDIO.getProductId();
            }
            // 修正已失效产品ID lhl-2021.01.08
            productId = ProductIdUtil.getNewProductId(productId);
            if (!NumberUtil.isNullOrZero(productId)) {
                ProductBaseQuery productDIO = new ProductBaseQuery();
                productDIO.setProductId(productId);
                com.zmn.common.dto2.ResponseDTO<List<ProductBaseDRO>> productDROResp = productForeignListRemoteService
                        .listBaseDROByQuery(productDIO);
                Optional.ofNullable(productDROResp.getData())
                        .map(list -> list.get(0))
                        .ifPresent(productBaseDRO -> {
                            orderAddDIO.setServCategId(productBaseDRO.getServCategId());

                            // 修正是否是前台产品ID
                            if (Objects.equals(GlobalConsts.YES, productBaseDRO.getShowType())) {
                                orderProductDIO.setShowProductId(productBaseDRO.getProductId());
                                orderProductDIO.setProductId(0);
                            }
                            else {
                                orderProductDIO.setProductId(productBaseDRO.getProductId());
                            }
                        });
            }

            if (orderAddDIO.getServCategId() == null) {
                orderProductDIO.setProductId(OrderConsts.CHANNEL_DISABLED_PRODUCT_ID);
                orderAddDIO.setServCategId(GlobalConsts.SERV_CATEG_REPAIR);
            }
        } catch (Exception e) {
            throw new OmsBaseException("产品不存在", e);
        }

        OrderBaseInfo orderBaseInfo = orderAddDIO.getOrderBaseInfo();
        ChannelApiExtraData channelApiExtraData = orderAddDIO.getChannelApiExtraData();
        OrderProductDIO orderProductDIO = orderAddDIO.getOrderProductList().get(0);
        UserDIO userDIO = orderAddDIO.getUserDIO();

        Integer channelId = createOrderDTO.getChannelId();
        Integer servCategId = orderAddDIO.getServCategId();

        {// 处理渠道优惠，采用新的保存方式  2020-06-23 by lhl
            Integer orderDiscountAmount = channelDiscountService.getOrderDiscountAmount(createOrderDTO);
            if (NumberUtil.isNotNullOrZero(orderDiscountAmount)) {
                channelApiExtraData.setChannelDiscountAmount(orderDiscountAmount);
                logRemarkBuilder.add(String.format("渠道优惠：%s元", MoneyUtil.parseToYuanStr(orderDiscountAmount)));
            }

            // 设置默认服务项和渠道优惠，号码百事通APP
            if (Objects.equals(channelId, OrderConsts.CHANNEL_ID_HAOBAI_APP)
                    && Objects.equals(servCategId, GlobalConsts.SERV_CATEG_CLEAN)) {
                try {
                    // 设置默认服务项
                    GetServiceItemDTO getServiceItemDTO = GetServiceItemDTO.builder()
                            .channelId(channelId)
                            .productId(
                                    NumberUtil.isNullOrZero(orderProductDIO.getShowProductId())
                                            ? orderProductDIO.getProductId()
                                            : orderProductDIO.getShowProductId()
                            )
                            .sourceType(orderBaseInfo.getSourceType())
                            .platWork(orderBaseInfo.getPlat())
                            .productNumber(orderProductDIO.getNumber())
                            .cityId(userDIO.getCityId())
                            .bizType(com.zmn.consts.GlobalConsts.BIZ_TYPE_C)
                            .build();
                    logger.debug("为号百app设置默认服务项==[{}]", getServiceItemDTO);
                    List<OrderServiceItem> orderServiceItems = this.listDefaultServiceItem(getServiceItemDTO);

                    // 计算优惠
                    if (CollectionUtil.isNotNullOrEmpty(orderServiceItems)) {
                        logger.debug("服务项和价格不为空开始计算优惠: GetServiceItemDTO=[{}]",
                                JSON.toJSONString(getServiceItemDTO));

                        int originalAmount = orderServiceItems.stream().mapToInt(e -> e.getTotalPrice()).sum();
                        int totalAmount = Optional.ofNullable(createOrderDTO.getTotalAmount()).orElse(-1);

                        // 如果是要客订单，且没有设置优惠，塞“特殊优惠-全免-总公司承担”
                        if (Objects.equals(GlobalConsts.YES, createOrderDTO.getVvip())) {
                            channelApiExtraData.setVvip(GlobalConsts.YES);
                            channelApiExtraData.setUnusualDiscount(GlobalConsts.YES);
                            logRemarkBuilder.add("特殊优惠-全免-总公司承担");
                        }
                        // 存在订单金额（totalAmount != -1）且原价大于订单金额，设置渠道优惠
                        else if (totalAmount >= 0 &&originalAmount > totalAmount) {
                            int discountAmount = MathUtil.sub(originalAmount, totalAmount);
                            channelApiExtraData.setChannelDiscountAmount(discountAmount);
                            logRemarkBuilder.add(String.format("渠道优惠：%s元，按优惠后金额计算得出",
                                    MoneyUtil.parseToYuanStr(discountAmount)
                            ));
                        }
                    }
                } catch (Exception e) {
                    logger.error(e.getMessage(), e);
                }
            }

            // 总价为0时，并且已支付，设置优惠立减
            if (Objects.equals(servCategId, GlobalConsts.SERV_CATEG_CLEAN)
                    && Objects.equals(createOrderDTO.getTotalAmount(), 0)
                    && Objects.equals(createOrderDTO.getChannelPrepayStatus(), PayConsts.PAY_STATUS_DONE)
                    && Objects.equals(createOrderDTO.getChannelPrepayAmount(), 0)
                    && !NumberUtil.isNullOrZero(createOrderDTO.getOriginalAmount())) {
                // 可以处理订单
                channelApiExtraData.setDisableDiscard(GlobalConsts.NO);
            }
        }

        // 设置默认预约时间处理 2020-05-19 by lhl
        if (createOrderDTO.getDutyTime() == null) {
            do {
                // 天猫订单不设置默认预约时间（勤鸽店，B端，勤鸽管道疏通）
                if (TaobaoMapper.isTmallChannel(createOrderDTO.getChannelId())) {
                    break;
                }
                // 录单平台是言而有信的，不设置默认预约时间
                if (Objects.equals(GlobalConsts.PLAT_MARK_YEYX, orderBaseInfo.getPlat())) {
                    break;
                }

                orderProductDIO.setDutyTime(ThirdOrderUtil.getDefaultDutyTime());
            } while (false);
        } else {

            orderProductDIO.setDutyTime(createOrderDTO.getDutyTime());
        }

        // 操作人为渠道
        orderAddDIO.setOperatorType(Optional.ofNullable(createOrderDTO.getOperatorType()).orElse(GlobalConsts.OPERATE_USER_TYPE_CHANNEL));
        orderAddDIO.setOperatorId(NumberUtil.isNotNullOrZero(createOrderDTO.getOperatorId()) ?
                createOrderDTO.getOperatorId() : (long) createOrderDTO.getChannelId());
        orderAddDIO.setOperator(StringUtil.isNotBlank(createOrderDTO.getOperator()) ? createOrderDTO.getOperator() : "系统");
        if (logRemarkBuilder.length() > 1) {
            orderAddDIO.setOperatorRemark(logRemarkBuilder.toString());
        }

        // 第三方店铺ID
        if(StringUtils.isNotBlank(createOrderDTO.getExternalShopId())){
            ExternalShopDIO externalShopDIO = new ExternalShopDIO();
            externalShopDIO.setExternalShopId(createOrderDTO.getExternalShopId());
            orderAddDIO.setExternalShopInfo(externalShopDIO);
        }


        return orderAddDIO;
    }


    /**
     * 录入普通单
     * @param createOrderDTO
     * @return
     * @throws OmsBaseException
     */
    private ChannelApiOrderAddDIO buildNormalChannelApiOrderAddDIO(com.zmn.oms.model.dto.order.open.CreateOrderDTO createOrderDTO)
            throws OmsBaseException {
        ChannelApiOrderAddDIO orderAddDIO = new ChannelApiOrderAddDIO();
        StringJoiner logRemarkBuilder = new StringJoiner("；");

        if (StringUtil.isNotBlank(createOrderDTO.getRemark())) {
            logRemarkBuilder.add(createOrderDTO.getRemark());
        }

        {// 客户信息
            UserDIO userDIO = BeanMapper.map(createOrderDTO, UserDIO.class);
            orderAddDIO.setUserDIO(userDIO);

            userDIO.setUserName(
                    StringUtils.isNotBlank(userDIO.getContactName())
                            ? userDIO.getContactName()
                            : "未知"
            );
            // 日志记录经纬度信息
            if (userDIO.getLongitude() != null && userDIO.getLatitude() != null) {
                logRemarkBuilder.add(
                        String.format("经纬度：%s,%s", userDIO.getLongitude(), userDIO.getLatitude())
                );
            }
        }
        {// 订单信息
            OrderBaseInfo orderBaseInfo = BeanMapper.map(createOrderDTO, OrderBaseInfo.class);
            orderAddDIO.setOrderBaseInfo(orderBaseInfo);

            orderBaseInfo.setType(OrderConsts.ORDER_TYPE_NEW);
            orderBaseInfo.setReceiveEntranceId(GateTypeConsts.GATE_API_NORM);
            orderBaseInfo.setReceiverManner(OrderConsts.RECEIVE_MANNER_API);
            // 默认平台
            orderBaseInfo.setPlat(
                    Optional.ofNullable(orderBaseInfo.getPlat()).orElse(GlobalConsts.PLAT_MARK_ZMN)
            );
            // 默认api录入
            orderBaseInfo.setInputType(
                    Optional.ofNullable(orderBaseInfo.getInputType()).orElse(OrderConsts.ORDER_INPUT_TYPE_API)
            );
            // 默认业务类型为C端订单
            orderBaseInfo.setBizType(
                    Optional.ofNullable(orderBaseInfo.getBizType()).orElse(com.zmn.consts.GlobalConsts.BIZ_TYPE_C)
            );
        }
        {// 产品信息
            OrderProductDIO orderProductDIO = BeanMapper.map(createOrderDTO, OrderProductDIO.class);
            orderAddDIO.setOrderProductList(Lists.newArrayList(orderProductDIO));

            orderProductDIO.setNumber(
                    NumberUtil.isNullOrZero(createOrderDTO.getProductCount())
                            ? 1
                            : createOrderDTO.getProductCount()
            );
            // 设置默认预约时间处理 2020-05-18 by lhl
            if (orderProductDIO.getDutyTime() == null) {
                orderProductDIO.setDutyTime(ThirdOrderUtil.getDefaultDutyTime());
            }
        }
        {// 渠道扩展信息
            ChannelApiExtraData extraData = BeanMapper.map(createOrderDTO, ChannelApiExtraData.class);
            orderAddDIO.setChannelApiExtraData(extraData);

            extraData.setOuterId(createOrderDTO.getThirdOrderId());
            extraData.setOuterData(createOrderDTO.getOuterJsonData());
            if (StringUtils.isNotBlank(createOrderDTO.getExtraData())) {
                extraData.setExtraData(createOrderDTO.getExtraData());
            }
            if (StringUtils.isNotBlank(createOrderDTO.getThirdOrderId2())) {
                extraData.setExtOuterId(createOrderDTO.getThirdOrderId2());
            }
        }

        // 通过产品查询服务分类
        try {
            OrderProductDIO orderProductDIO = orderAddDIO.getOrderProductList().get(0);
            orderAddDIO.setServCategId(null);

            Integer productId = orderProductDIO.getProductId();
            // 修正已失效产品ID lhl-2021.01.08
            productId = ProductIdUtil.getNewProductId(productId);
            if (!NumberUtil.isNullOrZero(productId)) {
                ProductBaseQuery productDIO = new ProductBaseQuery();
                productDIO.setProductId(productId);
                com.zmn.common.dto2.ResponseDTO<List<ProductBaseDRO>> productDROResp = productForeignListRemoteService
                        .listBaseDROByQuery(productDIO);
                Optional.ofNullable(productDROResp.getData())
                        .map(list -> list.get(0))
                        .ifPresent(productBaseDRO -> {
                            orderAddDIO.setServCategId(productBaseDRO.getServCategId());

                            // 修正是否是前台产品ID
                            if (Objects.equals(GlobalConsts.YES, productBaseDRO.getShowType())) {
                                orderProductDIO.setShowProductId(productBaseDRO.getProductId());
                                orderProductDIO.setProductId(0);
                            }
                            else {
                                orderProductDIO.setProductId(productBaseDRO.getProductId());
                            }
                        });
            }

            if (orderAddDIO.getServCategId() == null) {
                orderProductDIO.setProductId(OrderConsts.CHANNEL_DISABLED_PRODUCT_ID);
                orderAddDIO.setServCategId(GlobalConsts.SERV_CATEG_REPAIR);
            }
        } catch (Exception e) {
            throw new OmsBaseException("产品不存在", e);
        }

        ChannelApiExtraData channelApiExtraData = orderAddDIO.getChannelApiExtraData();

        // 处理渠道优惠信息，采用新的保存方式  2020-06-23 by lhl
        Optional.ofNullable(createOrderDTO.getOrderDiscount())
                .ifPresent(orderDiscount -> {
                    channelApiExtraData.setChannelDiscountAmount(orderDiscount.getAmount());

                    logRemarkBuilder.add(String.format("渠道优惠：%s元，备注：%s，%s",
                            MoneyUtil.parseToYuanStr(orderDiscount.getAmount()),
                            orderDiscount.getRemark(),
                            orderDiscount.getSourceData()
                    ));
                });

        {// 预付款数据处理  lhl-2020.12.03
            /*
                1. 修正渠道预付款的支付状态，防止接口提交非法数据；
                2. 有预付款且未支付时，设置订单不能弃单，也不能自动确认；
             */
            Integer channelPrepayAmount = channelApiExtraData.getChannelPrepayAmount();
            if (channelPrepayAmount == null) {
                // 没传预付款字段时，也不会有预付款支付状态
                channelApiExtraData.setChannelPrepayStatus(null);
                channelApiExtraData.setDisableDiscard(GlobalConsts.NO);
            }
            else {
                boolean isPaid = NumberUtil.isNotNullOrZero(channelPrepayAmount)
                        && Objects.equals(PayConsts.PAY_STATUS_DONE, createOrderDTO.getChannelPrepayStatus());
                channelApiExtraData.setChannelPrepayStatus(isPaid ? PayConsts.PAY_STATUS_DONE : PayConsts.PAY_STATUS_NONE);
                channelApiExtraData.setDisableDiscard(isPaid ? GlobalConsts.NO : GlobalConsts.YES);
            }
        }

        // 操作人为渠道
        orderAddDIO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_CHANNEL);
        orderAddDIO.setOperatorId((long) createOrderDTO.getChannelId());
        orderAddDIO.setOperator("系统");
        if (logRemarkBuilder.length() > 1) {
            orderAddDIO.setOperatorRemark(logRemarkBuilder.toString());
        }

        return orderAddDIO;
    }
    // endregion

}
